package hexapawn.ai;

import java.util.LinkedList;
import java.util.List;

import hexapawn.game.Board;
import hexapawn.game.Cell;
import hexapawn.game.MinimaxTree;
import hexapawn.game.Move;
import hexapawn.game.Player;

public class MiniMaxPlayer extends Player{

	public MiniMaxPlayer(Board _board) {
		super(_board, Player.PLAYER_MINIMAX);
	}

	@Override
	protected void removeTarget(Cell target){
		Player other = board.getTopPlayer();
		other.getPieces().remove(target.getPiece());
	}
	
	/**
	 * This should be modified to w/e Mini-Max AI do to make a move.
	 * 
	 */
	@Override
	public void makeMove(Cell to){
		
	}
	
	/**
	 * This is just a copy of what TopPlayer.java does. For a Mini-Max AI, this
	 * probably be more useful if it returns a List of Board objects that represents
	 * all possible moves given its pieces. However, because this is an abstract
	 * method. You can simply ignore this and implement w/e method you need to make
	 * the "makeMove()" method actually make a move by the Mini-Max AI.
	 * 
	 */
	@Override
	public List<Cell> getPossibleMoves(Cell _from) {
		List<Cell> possibleMoves = new LinkedList<Cell>();
		from = _from;
		int row = from.getRow();
		int col = from.getColumn();
		if(row-1 >= 0){
			Cell above, aboveLeft, aboveRight;
			above = board.getCellAbove(from);
			if(!above.hasPiece()) possibleMoves.add(above);
			if(col-1 >= 0){
				aboveLeft = board.getCellAboveLeft(from);
				if(aboveLeft.hasPiece())
					if(aboveLeft.getPiece().getOwner() == PLAYER_MDP)	possibleMoves.add(aboveLeft);
			}
			if(col+1 < board.getColumn()){
				aboveRight = board.getCellAboveRight(from);
				if(aboveRight.hasPiece())
					if(aboveRight.getPiece().getOwner() == PLAYER_MDP) possibleMoves.add(aboveRight);
			}
		}
		if(possibleMoves.size() == 0) from = null;
		return possibleMoves;
	}
	
	public int evalFeatures(MinimaxTree t){
		return evalFeatureValues(t, Player.PLAYER_MINIMAX);
	}
	
	public int evalFeatureValues(MinimaxTree t, int player){
		int value = 0;
		int nextPlayer;
		if(player == Player.PLAYER_MINIMAX || player == Player.PLAYER_2)
			nextPlayer = Player.PLAYER_1;
		else
			nextPlayer = Player.PLAYER_MINIMAX;
		value += t.evalFeatures(player);
		List<MinimaxTree> children = t.getChildren();
		for(MinimaxTree tree : children)
			value += evalFeatureValues(tree, nextPlayer);
		return value;
	}
	
	public MinimaxTree makeMinimaxTree(Board b, int levels){
		MinimaxTree mt = new MinimaxTree(null, b);
		MinimaxTree result = generateMinimaxNode(mt, levels);
		return result;
	}
	
	public MinimaxTree generateMinimaxNode(MinimaxTree parent, int levels){
		if(levels == 0)
			return parent;
		Board b = parent.getBoard();
		List<Board> bl = getPossibleBoards(b, (levels%2 == 0));
		for(Board board : bl) {
			parent.addChild(new MinimaxTree(parent, board));
		}
		for(MinimaxTree t : parent.getChildren()){
			generateMinimaxNode(t,levels-1);
		}
		return parent;
	}

	public List<Board> getPossibleBoards(Board b, boolean self){
		List<Board> bl = new LinkedList<Board>();
		List<Move> ml = new LinkedList<Move>();
		List<Cell> cl;
		if(self){
			cl = b.getBottomPlayerCells();
			for(Cell c : cl){
				List<Cell> pml = getPossibleMoves(b, c);
				for(Cell pc : pml){
					ml.add(new Move(c,pc));
				}
			}
			for(Move m :ml) {
				bl.add(b.applyMove(m));
			}
		}else{
			cl = b.getTopPlayerCells();
			MDPPlayer other = (MDPPlayer)b.getTopPlayer();
			for(Cell c : cl){
				List<Cell> pml = other.getPossibleMoves(b, c);
				for(Cell pc : pml){
					ml.add(new Move(c,pc));
				}
			}
			for(Move m :ml) {
				bl.add(b.applyMove(m));
			}
		}
		return bl;
	}
	
	public List<Cell> getPossibleMoves(Board b, Cell _from) {
		List<Cell> possibleMoves = new LinkedList<Cell>();
		from = _from;
		int row = from.getRow();
		int col = from.getColumn();
		if(row-1 >= 0){
			Cell above, aboveLeft, aboveRight;
			above = b.getCellAbove(from);
			if(!above.hasPiece()) possibleMoves.add(above);
			if(col-1 >= 0){
				aboveLeft = b.getCellAboveLeft(from);
				if(aboveLeft.hasPiece())
					if(aboveLeft.getPiece().getOwner() == PLAYER_MDP)	possibleMoves.add(aboveLeft);
			}
			if(col+1 < b.getColumn()){
				aboveRight = b.getCellAboveRight(from);
				if(aboveRight.hasPiece())
					if(aboveRight.getPiece().getOwner() == PLAYER_MDP) possibleMoves.add(aboveRight);

			}
		}

		if(possibleMoves.size() == 0) from = null;
		return possibleMoves;
	}
	
	

}
